

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_sntp.h"
#include "esp_netif_sntp.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "cJSON.h"

#include "wifi_sta.h"
#include "mqttc.h"
#include "custom.h"

#define TAG "appm"
static struct mqttc_handler mqc_handler;

static void custom_sntp_sync_time(struct timeval *tv)
{
    ESP_LOGI(TAG, "Notification of a time synchronization event");
}
static void app_sntp_init(void)
{
    esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("ntp.ntsc.ac.cn");
    config.sync_cb = custom_sntp_sync_time;
    time_t cur = time(NULL);
    struct tm tminfo;
    localtime_r(&cur, &tminfo);
    if(tminfo.tm_year < (2020 - 1900))
    {
        esp_netif_sntp_init(&config);
    }
}
static void app_main_entry(void *p)
{
    struct mqttc_handler *mqc = (struct mqttc_handler *)p;
    TickType_t cur_tick = 0;
    esp_err_t (*sntp_sync_wait)(TickType_t tout) = esp_netif_sntp_sync_wait;
    ESP_LOGI(TAG, "app run.%p", mqc);
    while(1)
    {
        if(ESP_OK == wifi_sta_wait_ready(100 / portTICK_PERIOD_MS))
        {
            if(mqttc_is_disconnected(mqc))
            {
                ESP_LOGI(TAG, "start mqtt.");
                mqttc_start(mqc);
            }
            if(sntp_sync_wait)
            {
                esp_err_t ret = sntp_sync_wait(100 / portTICK_PERIOD_MS);
                if(ret == ESP_OK)
                {
                    esp_netif_sntp_deinit();
                    sntp_sync_wait = NULL;
                    ESP_LOGI(TAG, "sntp stop.");
                }
                else if(ret == ESP_ERR_INVALID_STATE)
                {
                    app_sntp_init();
                    ESP_LOGI(TAG, "sntp start.");
                }
            }
        }
        int c = getchar();
        while(c != EOF)
        {
            putchar(c);
            c = getchar();
        }
        vTaskDelayUntil(&cur_tick, 500 / portTICK_PERIOD_MS);
        custom_update_time(NULL);
    }
}
static void mqttc_data_arrived(void *handler, const char *topic, int topic_len, uint8_t *data, int data_len)
{
    printf("TOPIC=%.*s, DATA=%.*s\r\n", topic_len, topic, data_len, data);
    if(strncmp(topic, D2C_HEATBEAT, topic_len) == 0)
    {
        /*
        format:
        {"device":"<devid>","type":0}
        type:0=led,1=humidity and temperature sensor
        */
        cJSON *data_root = cJSON_Parse((char *)data);
        struct mqttc_handler *mqc = (struct mqttc_handler *)handler;
        do
        {
            if(data_root == NULL)
            {
                break;
            }
            int led;
            cJSON *item = cJSON_GetObjectItem(data_root, "led");
            if(item == NULL)
            {
                break;
            }
            led = item->valueint;
            item = cJSON_GetObjectItem(data_root, "device");
            if(item == NULL)
            {
                break;
            }
            const char *device = item->valuestring;
            ESP_LOGI(TAG, "device:%s, led:%d", device, led);
            if(custom_check_device_list(&guider_ui, device) == false)
            {
                if(mqttc_device_subscribe(mqc, device) != ESP_OK)
                {
                    ESP_LOGE(TAG, "sub failed:%p");
                    break;
                }
                custom_add_device_list(&guider_ui, device);
            }
            char humi[8];
            char temp[8];
            item = cJSON_GetObjectItem(data_root, "humi");
            if(item != NULL)
            {
                int int_val = item->valueint;
                int decimal_val = int_val%10;
                if(decimal_val < 0)
                {
                    decimal_val = -decimal_val;
                }
                int_val /= 10;
                snprintf(humi, sizeof(humi), "%d.%d", int_val, decimal_val);
            }
            else
            {
                humi[0] = '\0';
            }
            item = cJSON_GetObjectItem(data_root, "temp");
            if(item != NULL)
            {
                int int_val = item->valueint;
                int decimal_val = int_val%10;
                if(decimal_val < 0)
                {
                    decimal_val = -decimal_val;
                }
                int_val /= 10;
                snprintf(temp, sizeof(temp), "%d.%d", int_val, decimal_val);
            }
            else
            {
                temp[0] = '\0';
            }
            custom_update_device_data(&guider_ui, led, humi, temp);
        }while(0);
        if(data_root)
        {
            cJSON_Delete(data_root);
            data_root = NULL;
        }
    }
}
void app_main_init(void)
{
    wifi_sta_init();
    mqttc_init(&mqc_handler, mqttc_data_arrived, 5);
    ESP_LOGI(TAG, "init...%p", &mqc_handler);
    if(xTaskCreatePinnedToCore(app_main_entry, "appm", 8192, &mqc_handler, 5, NULL, 0) != pdPASS)
    {
        ESP_ERROR_CHECK(ESP_FAIL);
    }
    ESP_LOGI(TAG, "OK");
}
void appm_set_led_status(const char *device, int led)
{
    if(device)
    {
        mqttc_device_publish_led_req(&mqc_handler, device, led);
    }
}


